#include <stdio.h>
#include <stdlib.h>
-#define MYNAME "gdbfile"
+#define MYNAME "gbfile"
+
+
+/* GPSBabel 'file' standard calls */
gbfile *
gbfopen(const char *filename, const char *mode, const char *module)
}
if (file->gzapi) {
- file->f = gzopen(filename, mode);
- if (file->f == NULL) {
+ file->handle.gz = gzopen(filename, mode);
+ if (file->handle.gz == NULL) {
fatal("%s: Cannot %s file '%s'!\n",
module,
(file->mode == 'r') ? "open" : "create",
file->gzapi = 1;
}
else {
- file->f = xfopen(filename, mode, module);
+ file->handle.std = xfopen(filename, mode, module);
}
+#ifdef DEBUG_MEM
+ file->buffsz = 1;
+#else
+ file->buffsz = 256;
+#endif
+ file->buff = xmalloc(file->buffsz);
return file;
}
if (!file) return;
if (file->gzapi) {
- gzclose( (gzFile *) file->f);
+ gzclose(file->handle.gz);
}
else {
- fclose( (FILE *) file->f);
+ fclose(file->handle.std);
}
xfree(file->name);
xfree(file->module);
xfree(file->line);
+ xfree(file->buff);
xfree(file);
}
{
unsigned char c;
- /* errors are catched in gbfread */
+ /* errors are caught in gbfread */
if (gbfread(&c, 1, 1, file) == 0) {
return EOF;
}
}
char *
-gbfgets(gbfile *file, char *buf, int len)
+gbfgets(char *buf, int len, gbfile *file)
{
- if (file->gzapi) {
- return gzgets( (gzFile *) file->f, buf, len);
- }
- else {
- return fgets(buf, len, (FILE *) file->f);
+ char *result = buf;
+
+ while (--len > 0) {
+ int c = gbfgetc(file);
+
+ if (c == EOF) break;
+
+ *(unsigned char *)buf = (unsigned char)c;
+ buf++;
+
+ if (c == '\r') {
+ c = gbfgetc(file);
+ if ((c != '\n') && (c != EOF)) gbfungetc(c, file);
+ break;
+ }
+ else if (c == '\n')
+ break;
}
+ *buf = '\0';
+ return (*result != '\0') ? result : NULL;
}
if ((size == 0) || (members == 0)) return 0;
if (file->gzapi) {
- int result = gzread( (gzFile *) file->f, buf, size * members) / size;
+ int result = gzread(file->handle.gz, buf, size * members) / size;
if ((result < 0) || ((gbsize_t)result < members)) {
int errnum;
const char *errtxt;
- errtxt = gzerror( (gzFile *) file->f, &errnum);
+ errtxt = gzerror(file->handle.gz, &errnum);
if ((errnum != Z_STREAM_END) && (errnum != 0))
fatal("%s: zlib returned error %d ('%s')!\n",
file->module, errnum, errtxt);
}
else {
int errno;
- gbsize_t result = fread(buf, size, members, (FILE *) file->f);
+ gbsize_t result = fread(buf, size, members, file->handle.std);
- if ((result < members) && (errno = ferror( (FILE *) file->f))) {
+ if ((result < members) && (errno = ferror(file->handle.std))) {
fatal("%s: Error %d occured during read of file '%s'!\n",
file->module, errno, file->name);
}
int
gbfprintf(gbfile *file, const char *format, ...)
{
- int len, result;
- char *buf;
- va_list args;
- char tmp[256]; /* probably enough for 99.9 percent of our code */
+ int len;
- va_start(args, format);
- len = vsnprintf(tmp, sizeof(tmp), format, args);
- va_end(args);
-
- if (len < sizeof(tmp)) buf = tmp;
- else {
- buf = xmalloc(len + 1);
+ for (;;) {
+ va_list args;
va_start(args, format);
- vsnprintf(buf, len + 1, format, args);
+ len = vsnprintf(file->buff, file->buffsz, format, args);
va_end(args);
+
+ if (len < 0)
+ fatal(MYNAME ": Unexpected vsnprintf error %d (%s/%s)!\n",
+ len, file->module, file->name);
+ else if (len == 0)
+ return 0;
+ else if (len < file->buffsz)
+ break;
+
+ while (file->buffsz <= len)
+ file->buffsz *= 2;
+
+ file->buff = xrealloc(file->buff, file->buffsz);
}
- result = gbfwrite(buf, 1, len, file);
- if (buf != tmp) xfree(buf);
-
- return result;
+ return gbfwrite(file->buff, 1, len, file);
}
int
if ((size == 0) || (members == 0)) return 0;
if (file->gzapi) {
- result = gzwrite( (gzFile *) file->f, buf, size * members) / size;
+ result = gzwrite(file->handle.gz, buf, size * members) / size;
}
else {
- result = fwrite(buf, size, members, (FILE *) file->f);
+ result = fwrite(buf, size, members, file->handle.std);
}
if (result != members) {
gbfflush(gbfile *file)
{
if (file->gzapi) {
- return gzflush( (gzFile *) file->f, Z_SYNC_FLUSH);
+ return gzflush(file->handle.gz, Z_SYNC_FLUSH);
}
else {
- return fflush( (FILE *) file->f);
+ return fflush(file->handle.std);
}
}
gbfclearerr(gbfile *file)
{
if (file->gzapi) {
- gzclearerr( (gzFile *) file->f);
+ gzclearerr(file->handle.gz);
}
else {
- clearerr( (FILE *) file->f);
+ clearerr(file->handle.std);
}
}
int errnum;
if (file->gzapi) {
- (void)gzerror( (gzFile *) file->f, &errnum);
+ (void)gzerror(file->handle.gz, &errnum);
}
else {
- errnum = ferror( (FILE *) file->f);
+ errnum = ferror(file->handle.std);
}
return errnum;
}
void
gbfrewind(gbfile *file)
{
- if (file->gzapi) {
- gzrewind( (gzFile *) file->f);
- }
- else {
- rewind( (FILE *) file->f);
- }
+ (void)gbfseek(file, 0, SEEK_SET);
+ gbfclearerr(file);
}
int
-gbfseek(gbfile *file, gbsize_t offset, int whence)
+gbfseek(gbfile *file, gbint32 offset, int whence)
{
- int result;
-
+
if (file->gzapi) {
+ int result;
+
assert(whence != SEEK_END);
- result = gzseek( (gzFile *) file->f, offset, whence);
+ result = gzseek(file->handle.gz, offset, whence);
is_fatal(result < 0,
"%s: online compression not yet supported for this format!", file->module);
return 0;
}
else {
- return fseek( (FILE *) file->f, offset, whence);
+ return fseek(file->handle.std, offset, whence);
}
}
gbftell(gbfile *file)
{
if (file->gzapi) {
- return gztell( (gzFile *) file->f);
+ return gztell(file->handle.gz);
}
else {
- return ftell( (FILE *) file->f);
+ return ftell(file->handle.std);
}
}
gbfeof(gbfile *file)
{
if (file->gzapi) {
- return gzeof( (gzFile *) file->f);
+ return gzeof(file->handle.gz);
}
else {
- return feof( (FILE *) file->f);
+ return feof(file->handle.std);
}
}
gbfungetc(const int c, gbfile *file)
{
if (file->gzapi) {
- return gzungetc(c, (gzFile *) file->f);
+ return gzungetc(c, file->handle.gz);
}
else {
- return ungetc(c, (FILE *) file->f);
+ return ungetc(c, file->handle.std);
}
}
-/* ----------------------------------------------------------- */
+/* GPSBabel 'file' enhancements */
gbint32
gbfgetint32(gbfile *file)
return result;
}
+float
+gbfgetflt(gbfile *file)
+{
+ union {
+ float f;
+ gbint32 i;
+ } x;
+
+ x.i = gbfgetint32(file);
+ return x.f;
+}
+
/*
* gbfgetcstr: Reads a string from file until either a '\0' or eof.
* The result is a temporary allocated entity: use it or free it!
}
/*
- * gbfgetstr: Reads a pascal string (first byte is length) from file.
+ * gbfgetpstr: Reads a pascal string (first byte is length) from file.
* The result is a temporary allocated entity: use it or free it!
*/
char *
}
/*
- * gbfgetstr: read a string from file (util any type of line-breaks or eof or error)
- * except free you can do all possible things with the result
+ * gbfgetstr: Reads a string from file (util any type of line-breaks or eof or error)
+ * except xfree and free you can do all possible things with the result
*/
char *
gbfgetstr(gbfile *file)
int len;
char *result = file->line;
- len = file->lsize = 0;
+ len = file->linesz = 0;
while (1) {
char c = gbfgetc(file);
else if (c == '\n') {
break;
}
- if (len == file->lsize) {
- file->lsize = len + 128;
+ if (len == file->linesz) {
+ file->linesz = len + 128;
result = file->line = xrealloc(file->line, len + 128 + 1);
}
result[len] = c;
return gbfwrite(buf, 1, sizeof(buf), file);
}
+int
+gbfputflt(const float f, gbfile *file)
+{
+ union {
+ float f;
+ gbint32 i; } x;
+
+ x.f = f;
+ return gbfputint32(x.i, file);
+}
+
+int
+gbfputcstr(const char *s, gbfile *file)
+{
+ return gbfwrite(s, 1, strlen(s) + 1, file)
+}
+
int
gbfputpstr(const char *s, gbfile *file)
{
int len;
len = strlen(s);
- if (len > 255) len = 255;
+ if (len > 255)
+ len = 255;
gbfputc(len, file);
gbfwrite(s, 1, len, file);
return len + 1;
}
+
+/* Thats all, sorry */
#include "zlib/zlib.h"
#include <stdarg.h>
-
typedef struct gbfile_s {
#ifdef DEBUG_MEM
void *dummy; /* ZERO pointer for stdio oop's */
#endif
- void *f;
+ union {
+ FILE *std;
+ gzFile *gz;
+ } handle;
char *name;
char *module;
char *line;
- int lsize;
+ int linesz;
+ char *buff; /* static growing buffer, primary used by gbprintf */
+ int buffsz;
char mode;
unsigned char big_endian:1;
unsigned char binary:1;
gbsize_t gbfread(void *buf, const gbsize_t size, const gbsize_t members, gbfile *file);
int gbfgetc(gbfile *file);
-char *gbfgets(gbfile *file, char *buf, int len);
+char *gbfgets(char *buf, int len, gbfile *file);
int gbfprintf(gbfile *file, const char *format, ...);
int gbfputc(int c, gbfile *file);
void gbfclearerr(gbfile *file);
int gbferror(gbfile *file);
void gbfrewind(gbfile *file);
-int gbfseek(gbfile *file, gbsize_t offset, int whence);
+int gbfseek(gbfile *file, gbint32 offset, int whence);
gbsize_t gbftell(gbfile *file);
int gbfeof(gbfile *file);
int gbfungetc(const int c, gbfile *file);
gbint32 gbfgetint32(gbfile *file);
-#define gbfgetuint32(a) (gbuint32)gbfgetint32((a))
+#define gbfgetuint32 (gbuint32)gbfgetint32
gbint16 gbfgetint16(gbfile *file);
-#define gbfgetuint16(a) (gbuint16)gbfgetint16((a))
-double gbfgetdbl(gbfile *file); // read double value
-char *gbfgetstr(gbfile *file); // read until any type of line-breaks of EOF
+#define gbfgetuint16 (gbuint16)gbfgetint16
+double gbfgetdbl(gbfile *file); // read a double value
+float gbfgetflt(gbfile *file); // read a float value
+char *gbfgetstr(gbfile *file); // read until any type of line-breaks or EOF
char *gbfgetpstr(gbfile *file); // read a pascal string
int gbfputint16(const gbint16 i, gbfile *file);
-#define gbfputuint16 gbfputint16((gbuint16)(a),(b))
+#define gbfputuint16(a,b) gbfputint16((gbuint16)(a),(b))
int gbfputint32(const gbint32 i, gbfile *file);
#define gbfputuint32(a,b) gbfputint16((gbuint32)(a),(b))
-int gbfputdbl(const double d, gbfile *file); // write double value
+int gbfputdbl(const double d, gbfile *file); // write a double value
+int gbfputflt(const float f, gbfile *file); // write a float value
+int gbfputcstr(const char *s, gbfile *file); // write string including '\0'
int gbfputpstr(const char *s, gbfile *file); // write as pascal string
#endif